import "express-async-errors";
import type { Application, NextFunction, Request, Response } from "express";
import mongoose from "mongoose";
import z from "zod";
import { AssertionError } from "assert";
import { errorLog, commLog } from "../utils/log";
import { traceLog } from "../middlewares/traceLog";
import { getServerAPIList } from "../rpc/core/apilist";
import { createApiFile, dispatchRpc } from "../rpc/core";
import env from "@/utils/env";
import MessageCode from "@monorepo/shared/validators/core/MessageCode";

/** 解析错误信息字符串 格式为 'msg:code'*/
const parseError = (errMsg: string) => {
  const arr = errMsg.split(":");
  const code = Number(arr[1].trim());
  const msg = arr[0].trim();
  return {
    code,
    msg,
  };
};

/** 解析 zod 错误 */
const parserZodError = (param: z.ZodError) => {
  if (param.errors.length === 0) return { code: 200, msg: "ok" };
  const m = param.errors[0].message;
  return parseError(m);
};

const router = async (app: Application) => {
  //* 加载日志中间件
  app.use(traceLog);

  /**
   * 开发模式下，开启前端接口开发服务
   */
  if (env.NODE_ENV === "development") {
    /** 注册控制器以及方法 */
    await import("@/rpc/core/register");

    // 生成API接口代码
    if (env.MONOREPO_AUTO_CREATE_API_WRAPPER) createApiFile();
    // API接口列表
    app.get(`${env.RPC_API_URL}/reference`, getServerAPIList);

    //* 服务器测试使用
    app.get("/", (req: Request, res: Response) => {
      res.send("Server is running");
    });
  }

  app.post(env.RPC_API_URL, dispatchRpc, (req: Request, res: Response) => {
    //** 统一返回数据
    if (req.data)
      res.send({
        code: 200,
        msg: "ok",
        data: req.data,
      });
    else
      res.send({
        code: 200,
        msg: "ok",
      });
    req.data = null;
  });

  //* 处理异常
  app.use((err: unknown, req: Request, res: Response, next: NextFunction) => {
    if (!err) {
      return next();
    }

    // 记录错误日志
    errorLog.error(err);

    // 显示调试信息
    commLog.debug(err);

    // 如果事务存在则中断事务
    if (req.isDBTransaction) {
      req.isDBTransaction = false;
      req.dbSession?.abortTransaction();
      req.dbSession = null;
      commLog.error("事务异常已中断");
    }

    // zod参数校验引发的error
    if (err instanceof z.ZodError || (err as z.ZodError).name === "ZodError") {
      const e = err as z.ZodError;
      commLog.error("参数校验引发的error，来自 - ", e.message);
      res.send(parserZodError(e));
    }
    // assert抛出的error
    else if (err instanceof AssertionError) {
      commLog.error("assert抛出的error，来自 - ", err.message);
      res.send(parseError(err.message));
    }
    // 数据库操作引发的异常
    else if (err instanceof mongoose.Error) {
      commLog.error("数据库操作引发的异常，来自 - ", err.message);
      if (err.name === "ValidationError")
        res.send(parseError(MessageCode.Public.db.validation));
      else {
        // 未知的数据库错误
        res.send(parseError(MessageCode.Public.db.unknown));
      }
    } else if (err instanceof SyntaxError) {
      commLog.error("JSON语法错误，来自 - ", err.message);
      res.send(parseError(MessageCode.Public.json.syntax));
    }
    // 未知引发的异常
    else {
      commLog.error("未知引发的异常，来自 - ", err);
      res.send({
        code: 1000,
        msg: "未知的错误",
      });
    }
  });
};

export default router;
